package io.esirong.widget.media;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Color;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Environment;
import android.os.PowerManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import android.widget.VideoView;

import androidx.annotation.RequiresApi;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import static android.content.ContentValues.TAG;

public class CameraView2 extends RelativeLayout implements SurfaceHolder.Callback, Camera.AutoFocusCallback {

    private MediaRecorder mediaRecorder;

    private ImageView picPreImageView;
    private CaptureButton4 mCaptureButton;
    private boolean autoFocus;
    private boolean isRecorder;
    private boolean isRecording; // 标记，判断当前是否正在录制
    private boolean isPlay;
    private boolean isPre;
    private String fileName;
    private float screenProp;
    private String videoFileName;

    public CameraView2(Context context) {
        super(context);
        init();
    }

    public CameraView2(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CameraView2(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public CameraView2(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private Context mContext;
    private VideoView mVideoView;
    private Camera mCamera;
    private Camera.Parameters mParam;
    private PowerManager powerManager = null;
    private SurfaceHolder mHolder = null;

    private int SELECTED_CAMERA = -1;
    private int CAMERA_POST_POSITION = -1;
    private int CAMERA_FRONT_POSITION = -1;

    private void init() {
        mContext = getContext();
        powerManager = (PowerManager) mContext.getSystemService(mContext.POWER_SERVICE);
        findAvailableCameras();
        SELECTED_CAMERA = CAMERA_POST_POSITION;

        initView();
    }

    private Context context() {
        return getContext();
    }

    /**
     * 获得可用的相机，并设置前后摄像机的ID
     */
    private void findAvailableCameras() {
        Camera.CameraInfo info = new Camera.CameraInfo();
        int numCamera = Camera.getNumberOfCameras();
        for (int i = 0; i < numCamera; i++) {
            Camera.getCameraInfo(i, info);
            // 找到了前置摄像头
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                CAMERA_FRONT_POSITION = info.facing;
            }
            // 找到了后置摄像头
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                CAMERA_POST_POSITION = info.facing;
            }
        }
    }

    /**
     * 初始化View界面，含控件的初始化以及控件监听器的初始化
     */
    private void initView() {
        setWillNotDraw(false);
        this.setBackgroundColor(Color.BLACK);

        initVideoView();            //视频播放控件
        initPicPreImageView();      //预览
        initCaptureButton();        //录像按钮
        initCameraChangeButton();   //切换摄像头
        initFocusView();            //对焦视图
        initSurfaceHolder();        //装载
    }

    private void initSurfaceHolder() {
        mHolder = mVideoView.getHolder();
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        // 设置该组件不会让屏幕自动关闭
        mHolder.setKeepScreenOn(true);
        mHolder.addCallback(this);
    }

    private void initFocusView() {

    }

    private void initCameraChangeButton() {
        //右上角切换摄像头的按钮
    }

    private void initCaptureButton() {
        //底部居中的录像/拍照按钮
        LayoutParams btnParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        btnParams.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
        btnParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
        mCaptureButton = new CaptureButton4(mContext);
        mCaptureButton.setLayoutParams(btnParams);

        //初始化为自动对焦
        autoFocus = true;
        initCaptureButtonListener();

        this.addView(mCaptureButton);   //录视频
    }

    private void initPicPreImageView() {
        LayoutParams picPreImageViewParam = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        picPreImageViewParam.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
        picPreImageView = new ImageView(context());
        picPreImageView.setLayoutParams(picPreImageViewParam);
        picPreImageView.setVisibility(INVISIBLE);

        this.addView(picPreImageView);  //预览
    }

    private void initVideoView() {
        /*VideoView 播放视频的界面*/
        mVideoView = new VideoView(context());
        LayoutParams videoViewParam = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        videoViewParam.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
        mVideoView.setLayoutParams(videoViewParam);
        this.addView(mVideoView);       //video View

        mVideoView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                mCamera.autoFocus(CameraView2.this);//
            }
        });
    }

    /**
     * 初始化拍照/录像按钮的监听器
     */
    private void initCaptureButtonListener() {
        mCaptureButton.setCaptureListener(new CaptureButton4.CaptureListener() {
            @Override
            public void capture() {
            }

            @Override
            public void cancel() {
                isRecorder = false;
                releaseCamera();
                getCamera(SELECTED_CAMERA);
                isPre = false;
                setStartPreview(mCamera, mHolder);
                picPreImageView.setVisibility(INVISIBLE);
            }

            @Override
            public void determine() {
                releaseCamera();
                isPre = false;
            }

            @Override
            public void quit() {
            }

            @Override
            public void record() {
                if (isRecorder) {
                    CameraView2.this.stopRecord();
                } else {
                    CameraView2.this.startRecord();
                }
            }

            @Override
            public void recordEnd() {
                CameraView2.this.stopRecord();
            }

            @Override
            public void getRecordResult() {

                mVideoView.stopPlayback();
                releaseCamera();
                isPlay = false;
            }

            @Override
            public void deleteRecordResult() {
                File file = new File(fileName);
                if (file.exists()) {
                    file.delete();
                }
                fileName = null;
                releaseCamera();

                mVideoView.pause();
                mVideoView.stopPlayback();  //整个界面销毁，各种按钮不存在了，依附于按钮的监听器也就不存在了

                isPlay = false;
                getCamera(SELECTED_CAMERA);
                setStartPreview(mCamera, mHolder);
            }

            @Override
            public void scale(float scaleValue) {
                if (scaleValue >= 0) {
                    int scaleRate = (int) (scaleValue / 50);

                    if (scaleRate < 10 && scaleRate >= 0 && mParam != null && mCamera != null && mParam
                            .isSmoothZoomSupported()) {
                        mParam = mCamera.getParameters();
                        mParam.setZoom(scaleRate);
                        mCamera.setParameters(mParam);
                    }
                }
            }
        });
    }

    private void capture() {

    }

    public void setSaveVideoPath(String path) {

    }

    /**
     * 创建视频文件保存路径
     */
    private File createRecordDir() {
        if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            Toast.makeText(getContext(), "请查看您的SD卡是否存在！", Toast.LENGTH_SHORT).show();
            return null;
        }

        File sampleDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "Record");
        if (!sampleDir.exists()) {
            sampleDir.mkdirs();
        }
        String recordName = "VID_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + ".mp4";
        videoFileName = new File(sampleDir, recordName).getAbsolutePath();
        return new File(sampleDir, recordName);
    }

    /**
     * 开始录像
     */
    private void startRecord() {
        if (isRecorder) {
            mediaRecorder.stop();
            mediaRecorder.release();
            mediaRecorder = null;
        }
        if (mCamera == null) {
            stopRecord();
            return;
        }
        mCamera.unlock();
        if (mediaRecorder == null) {
            mediaRecorder = new MediaRecorder();
        }
        mediaRecorder.reset();
        mediaRecorder.setCamera(mCamera);
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);

        if (Build.MODEL.contains("vivo X5Pro")) {
            mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
        } else {
            mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        }
        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        //在1加手机上,如果设置15,直接挂掉,好像是能接受的最大值是30,所以屏蔽掉
        //        mediaRecorder.setVideoFrameRate(15);//帧率

        if (mParam == null) {
            mParam = mCamera.getParameters();
        }
        Camera.Size videoSize = CameraParamUtil.getInstance().getPictureSize(CameraParamUtil.getSupportedVideoSizes
                (mParam), 1000, screenProp);

        mediaRecorder.setVideoSize(videoSize.width, videoSize.height);
        int rotationRecord = CameraParamUtil.getInstance().getCameraDisplayOrientation(getContext(), SELECTED_CAMERA);
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(SELECTED_CAMERA, info);
        int frontRotation;
        if (rotationRecord == 180) {
            //反向横屏的前置角度
            frontRotation = 180;
        } else {
            //竖屏和正向横屏的前置角度
            //录制下来的视屏选择角度，此处为前置
            frontRotation = (rotationRecord == 0) ? 270 - info.orientation : info.orientation;
        }
        mediaRecorder.setOrientationHint((SELECTED_CAMERA == 1) ? frontRotation : rotationRecord);
        mediaRecorder.setMaxDuration(10000);
        mediaRecorder.setVideoEncodingBitRate(1024 * 1024);
        mediaRecorder.setPreviewDisplay(mHolder.getSurface());
        File file = createRecordDir();
        mediaRecorder.setOutputFile(file.getPath());
        try {
            mediaRecorder.prepare();
            mediaRecorder.start();
            isRecorder = true;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            Log.d("错误", e.getMessage());
        }
    }

    private void stopRecord() {
        if (mediaRecorder != null) {
            mediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
                @Override
                public void onError(MediaRecorder mr, int what, int extra) {
                    Toast.makeText(mContext, "视频过短，请重新录制", Toast.LENGTH_SHORT).show();
                    if (mr != null) {
                        mr.reset();
                    }
                    mediaRecorder.release();
                    mediaRecorder = null;
                    isRecorder = false;
                    fileName = videoFileName;
                    File file = new File(fileName);
                    if (file.exists()) {
                        file.delete();
                    }
                    releaseCamera();
                    getCamera(SELECTED_CAMERA);
                    isPlay = false;
                    setStartPreview(mCamera, mHolder);
                    mCaptureButton.initButton();
                }
            });

            mediaRecorder.setOnInfoListener(null);
            mediaRecorder.setPreviewDisplay(null);
            try {
                mediaRecorder.stop();
                mediaRecorder.release();
                mediaRecorder = null;
                isRecorder = false;
            } catch (IllegalStateException e) {
                e.printStackTrace();
            }

            releaseCamera();


            fileName = videoFileName;
            File file = new File(fileName);
            if (file.exists() && file.length() > 0) {
                mVideoView.setVideoPath(fileName);
                mVideoView.start();

                mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                    @Override
                    public void onPrepared(MediaPlayer mp) {
                        isPlay = true;
                        mp.start();
                        mp.setLooping(true);
                    }
                });
                mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                    @Override
                    public void onCompletion(MediaPlayer mp) {
                        if (fileName != null) {
                            mVideoView.setVideoPath(fileName);
                            mVideoView.start();
                        }
                    }
                });

                mVideoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
                    @Override
                    public boolean onError(MediaPlayer mp, int what, int extra) {
                        Log.d("guo_zjin:", "mVideoView.setOnErrorListener,被release");
                        if (!isPre) {
                            releasePre();
                        }
                        return true;
                    }
                });
            } else {
                Toast.makeText(getContext(), "视频不存在，赶紧重拍一个吧~", Toast.LENGTH_LONG).show();
                Log.d("guo_zjin:", "stopRecorder,被release");
                releasePre();
            }
        }
    }

    //关闭预览
    private void releasePre() {
        if (mVideoView != null && mVideoView.isPlaying()) {
            mVideoView.stopPlayback();
        }
        if (mHolder != null) {
            mHolder.getSurface().release();
        }
        mCaptureButton.initButton();
        picPreImageView.setVisibility(INVISIBLE);
        // 区分一下是照片还是视频
        releaseCamera();
        isPre = false;
        isPlay = false;
        getCamera(SELECTED_CAMERA);
        setStartPreview(mCamera, mHolder);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        float widthSize = MeasureSpec.getSize(widthMeasureSpec);
        float heightSize = MeasureSpec.getSize(heightMeasureSpec);
        screenProp = heightSize / widthSize;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
    }

    //获取Camera
    private void getCamera(int position) {
        try {
            if (null == mCamera) {
                Log.d(CameraView2.class.getName(), "position:" + position);
                mCamera = Camera.open(position);
                Log.d("guo_zjin:", "create camera success");
            }
        } catch (RuntimeException e) {
            Log.d("guo_zjin:", "create camera Runtime Exception");
            AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
            builder.setTitle("提示").setMessage("没有照相机权限,请赋予本权限再开始拍照吧~").setPositiveButton("确定", new DialogInterface
                    .OnClickListener() {
                @Override
                public void onClick(DialogInterface arg0, int arg1) {

                }
            }).show();
        } catch (Exception e) {
            Log.d("guo_zjin:", "create camera Exception");
            mCamera = null;
            e.printStackTrace();
        }
    }

    private void setStartPreview(Camera camera, SurfaceHolder holder) {
        if (camera == null) {
            return;
        }

        this.invalidate();

        mParam = camera.getParameters();

        if (screenProp != 0) {
            Camera.Size previewSize = CameraParamUtil.getInstance().getPreviewSize(mParam.getSupportedPreviewSizes(),
                    1000, screenProp);
            Camera.Size pictureSize = CameraParamUtil.getInstance().getPictureSize(mParam.getSupportedPictureSizes(),
                    1200, screenProp);
            mParam.setPreviewSize(previewSize.width, previewSize.height);
            mParam.setPictureSize(pictureSize.width, pictureSize.height);
        }
        if (CameraParamUtil.getInstance().isSupportedFocusMode(mParam.getSupportedFocusModes(), Camera.Parameters
                .FOCUS_MODE_CONTINUOUS_VIDEO)) {
            mParam.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
        } else if (CameraParamUtil.getInstance().isSupportedFocusMode(mParam.getSupportedFocusModes(), Camera
                .Parameters.FOCUS_MODE_AUTO)) {
            mParam.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
        }
        if (CameraParamUtil.getInstance().isSupportedPictureFormats(mParam.getSupportedPictureFormats(), ImageFormat
                .JPEG)) {
            mParam.setPictureFormat(ImageFormat.JPEG);
            mParam.setJpegQuality(100);
        }
        camera.setParameters(mParam);
        try {
            Log.d("guo_zjin:", "发生错误的开始。。。。");
            camera.setPreviewDisplay(holder);
            Log.d("guo_zjin:", "发生错误的开始。。。。01");
            camera.setDisplayOrientation(CameraParamUtil.getInstance().getCameraDisplayOrientation(getContext(),
                    SELECTED_CAMERA));
            Log.d("guo_zjin:", "发生错误的开始。。。。02");

            camera.startPreview();
            Log.d("guo_zjin:", "发生错误的开始。。。。03");
        } catch (FileNotFoundException e) {
            Log.d("guo_zjin:", "在setStartPreview里发生文件不存在,被release");
            releasePre();
        } catch (IOException e) {
            Log.d("guo_zjin: ", "在这里发生了一个该死的异常,但是我不得不在这里处理掉。。。。。00" + e.getMessage());
        } catch (Exception e) {
            Log.d("guo_zjin:", "在这里发生了一个该死的异常,但是我不得不在这里处理掉。。。。。01" + e.getMessage());
        }
    }

    private void initCamera() {

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {

        //init Camera
        if (mCamera != null) {
            releaseCamera();
        }
        //默认启动后置摄像头
        getCamera(SELECTED_CAMERA);
        if (mCamera == null) {
            Toast.makeText(getContext(), "未能获取到相机！", Toast.LENGTH_SHORT).show();
            return;
        }
        try {
            if (mCamera != null) {
                mCamera.setPreviewDisplay(holder);
                mHolder = holder;
            }
            Log.d("surfaceCreated ", mHolder.getSurface().hashCode() + "");
        } catch (IOException exception) {
            Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        Log.d("拍摄视频", "surfaceChanged");
        if (mHolder.getSurface() == null) {
            return;
        }
        mHolder = holder;
        // stop preview before making changes
        try {
            Log.d("", mHolder.hashCode() + "");

            if (null == mCamera) {
                getCamera(SELECTED_CAMERA);
            }
            mCamera.stopPreview();
            Log.d("", mHolder.hashCode() + "");
            setStartPreview(mCamera, holder);
        } catch (Exception e) {
            Log.d(TAG, "surfaceChanged Exception " + e.getMessage());
            Log.d(TAG, "Error starting camera preview: " + e.getMessage());
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        releaseCamera();
    }

    private void releaseCamera() {
        Log.d(TAG, "release Camera here.......");
        if (mCamera != null) {
            mCamera.stopPreview();
            try {
                mCamera.setPreviewDisplay(null);
            } catch (IOException e) {
                e.printStackTrace();
            }
            mCamera.setPreviewCallback(null);
            mCamera.release();
            mCamera = null;
        }
    }

    @Override
    public void onAutoFocus(boolean success, Camera camera) {

    }

    @Override
    public boolean onTouchEvent(final MotionEvent event) {
        if (!autoFocus && event.getAction() == MotionEvent.ACTION_DOWN && SELECTED_CAMERA == CAMERA_POST_POSITION &&
                !isPlay && !isPre) {
            if (mCamera != null) {
                mParam = mCamera.getParameters();
                mParam.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
                mCamera.setParameters(mParam);
            }
        }
        return super.onTouchEvent(event);
    }
}
